import logging
import json
import googlemaps
import os

import numpy as np
import pandas as pd

from .constants import OPT_PATH

class GoogleDistanceMatrixAPI:
    def __init__(self, config_path='config/Google_DM_params.json', opt_back_path=OPT_PATH):
        self.logger = logging.getLogger('DistanceMatrixAPI')
        self.logger.debug(f"Initializing DistanceMatrixAPI")
        try:
            with open(os.path.join(opt_back_path, config_path), 'r') as f:
                self.distance_matrix_params = json.load(f)
                self.gmaps = googlemaps.Client(
                    key=self.distance_matrix_params['key'])  # Google Maps client initialization
                self.distance_matrix_params.pop('key', None)
        except Exception as e:
            self.logger.error(f"Couldn't load config {config_path}, {e}")
            raise FileNotFoundError("Couldn't load config")

    def get_distance(self, origin, destinations, request_params):
        request_result = []
        self.logger.debug(f"Connecting to Google Maps API")
        self.distance_matrix_params['departure_time'] = request_params['date']
        matrix, attempts = None, 1
        while not matrix and attempts <= 3:
            try:
                matrix = self.gmaps.distance_matrix([origin], destinations, **self.distance_matrix_params)
            except googlemaps.exceptions.Timeout:
                self.logger.warning(f"Got timeout from Google API on attempt {attempts}, trying again")
                attempts += 1
        if not matrix:
            self.logger.error(f"Couldn't get distance matrix")
            return pd.DataFrame(columns=['origin', 'origin_norm', 'destination', 'destination_norm',
                                         'distance', 'duration', 'date', 'source'])
        for j, destination_inner in enumerate(destinations):
            element = matrix['rows'][0]['elements'][j]
            # print(j,' ', destination_inner)
            # print(element['status'])
            if element['status'] == 'OK':
                request_result.append((origin,
                                       matrix['origin_addresses'][0],
                                       destination_inner,
                                       matrix['destination_addresses'][j],
                                       element['distance']['value'],
                                       element['duration']['value'],
                                       self.distance_matrix_params['departure_time'].strftime('%Y-%m-%d'),
                                       'Google'))
            else:  # If status is not 'OK', fill distance with arbitrary large number
                request_result.append((origin, origin, destination_inner, destination_inner, np.nan, np.nan,
                                       self.distance_matrix_params['departure_time'].strftime('%Y-%m-%d'), 'Google'))
                self.logger.error(f"Google couldn't make a path between {origin} and {destination_inner}. Skipping")
        # print(request_result)
        request_result = pd.DataFrame(request_result,
                                      columns=['origin', 'origin_norm', 'destination', 'destination_norm',
                                               'distance', 'duration', 'date', 'source'])
        return request_result
